package com.ysd.lis.enums;

import com.ysd.lis.entity.WkTestOption;
import com.ysd.lis.entity.WkTestSmall;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;

@Getter
@AllArgsConstructor
public enum TestQuestionTypeEnum {

    single("single", "单项选择题",
            ValidateScoreTools.single,
            ValidateScoreTools.optionValueFunc),
    multiple("multiple", "多选题",
            ValidateScoreTools.multiple,
            ValidateScoreTools.optionValuesFunc),
    judge("judge", "判断题",
            ValidateScoreTools.judge,
            ValidateScoreTools.optionValueFunc),
    fill("fill", "填空题",
            ValidateScoreTools.fill,
            ValidateScoreTools.optionContentFunc),
    answer("answer", "简答题",
            ValidateScoreTools.answer,
            ValidateScoreTools.optionContentFunc),
    none("", "None",
            ValidateScoreTools.zero,
            ValidateScoreTools.Noting),
    ;

    private final String type;
    private final String value;
    private final BiFunction<List<WkTestOption>, WkTestSmall, Integer> func;
    private final Function<WkTestSmall, String> optionValueFunc;

    public static TestQuestionTypeEnum getValidate(String type) {
        return Arrays.stream(TestQuestionTypeEnum.values()).filter(ele -> ele.getType().equals(type)).findFirst().orElse(none);
    }

    public final static class ValidateScoreTools {

        static Function<WkTestSmall, String> Noting = (x) -> "";
        static BiFunction<List<WkTestOption>, WkTestSmall, Integer> zero = (x, y) -> 0;

        /**
         * 考生答题答案（填空、简答）
         */
        static Function<WkTestSmall, String> optionContentFunc = WkTestSmall::getWkTestValue;

        /**
         * 考生答题选中项(单选)
         */
        static Function<WkTestSmall, String> optionValueFunc = WkTestSmall::getCheckOption;

        /**
         * 考生答题选中集合(多选)
         */
        static Function<WkTestSmall, String> optionValuesFunc = (x) -> String.join(",", x.getCheckOptions());

        /**
         * 验证单选，并计算分数
         */
        static BiFunction<List<WkTestOption>, WkTestSmall, Integer> single = (wkTestOptions, wkTestSmall) -> {
            AtomicReference<Integer> scope = new AtomicReference<>(0);
            Optional<WkTestOption> first = wkTestOptions.stream().filter(option -> option.getOptionValue().equals(wkTestSmall.getCheckOption())).findFirst();
            first.ifPresent(option -> {
                if (option.getIsCorrect() == 1) {
                    scope.set(wkTestSmall.getScore());
                }
            });
            return scope.get();
        };

        /**
         * 验证判断题，并计算分数
         */
        static BiFunction<List<WkTestOption>, WkTestSmall, Integer> judge = (wkTestOptions, wkTestSmall) -> {
            AtomicReference<Integer> scope = new AtomicReference<>(0);
            Optional<WkTestOption> first = wkTestOptions.stream().filter(option -> option.getOptionValue().equals(wkTestSmall.getCheckOption())).findFirst();
            first.ifPresent(option -> {
                if (option.getIsCorrect() == 1) {
                    scope.set(wkTestSmall.getScore());
                }
            });
            return scope.get();
        };

        /**
         * 验证多项选择题，并计算分数
         */
        static BiFunction<List<WkTestOption>, WkTestSmall, Integer> multiple = (wkTestOptions, wkTestSmall) -> {
            List<String> collected = wkTestOptions.stream().filter(option -> option.getIsCorrect().equals(1)).map(item -> item.getOptionValue()).collect(Collectors.toList());
            List<String> checkOptions = wkTestSmall.getCheckOptions();
            Collections.sort(collected);
            Collections.sort(checkOptions);
            return collected.equals(checkOptions) ? wkTestSmall.getScore() : 0;
        };

        /**
         * 验证填空题，并计算分数
         */
        static BiFunction<List<WkTestOption>, WkTestSmall, Integer> fill = (wkTestOptions, wkTestSmall) -> {
            if (StringUtils.isBlank(wkTestSmall.getWkTestValue())) return 0;

            String[] split = wkTestSmall.getWkTestValue().split(",", -1);
            boolean flag = true;
            for (int i = 0; i < wkTestOptions.size(); i++) {
                if (!flag) break;
                WkTestOption wkTestOption = wkTestOptions.get(i);
                String s = split[i];
                if (wkTestOption.getMatchType().equals("allWith") && !wkTestOption.getOptionKeyword().equals(s))
                    flag = false;
                if (wkTestOption.getMatchType().equals("startWith") && !s.startsWith(wkTestOption.getOptionKeyword()))
                    flag = false;
                if (wkTestOption.getMatchType().equals("contains") && !s.contains(wkTestOption.getOptionKeyword()))
                    flag = false;
                if (wkTestOption.getMatchType().equals("endWith") && !s.endsWith(wkTestOption.getOptionKeyword()))
                    flag = false;
            }
            return flag ? wkTestSmall.getScore() : 0;
        };

        /**
         * 验证简答题，并计算分数
         */
        static BiFunction<List<WkTestOption>, WkTestSmall, Integer> answer = (wkTestOptions, wkTestSmall) -> {
            if (StringUtils.isBlank(wkTestSmall.getWkTestValue())) return 0;
            String wkTestValue = wkTestSmall.getWkTestValue();
            boolean flag = false;
            for (int i = 0; i < wkTestOptions.size(); i++) {
                if (wkTestValue.contains(wkTestOptions.get(i).getOptionKeyword())) {
                    flag = true;
                    break;
                }
            }
            return flag ? wkTestSmall.getScore() : 0;
        };

    }
}


